<template>
  <template v-if="props.format === 'hex'">
    <AInput v-bind="$attrs" prefix="#" v-model:value="hexValue" :maxlength="6" @change="onHexChange" />
  </template>
  <template v-else-if="props.format === 'rgb'">
    <ASpace>
      <AInputNumber
        v-bind="$attrs"
        v-for="key in Object.keys(rgbValue)"
        :key="key"
        v-model:value="rgbValue[key]"
        :min="0"
        :max="255"
        :step="1"
        style="width: 60px"
        @change="onRgbChange"
      />
    </ASpace>
  </template>
  <template v-else-if="props.format === 'hsb'">
    <ASpace>
      <AInputNumber
        v-bind="$attrs"
        v-for="key in Object.keys(hsbValue)"
        :key="key"
        v-model:value="hsbValue[key]"
        :min="0"
        :max="key === 'h' ? 360 : 100"
        :step="1"
        style="width: 60px"
        @change="onHsbChange"
      />
    </ASpace>
  </template>
</template>

<script setup>
import { onMounted, toValue, watch } from 'vue';
import { formatColor, hsbValid, isRgb } from '@/utils/color/index.js';
import { useState } from '@/hooks/index.js';

defineOptions({
  inheritAttrs: false
});

const props = defineProps({
  format: { type: String, default: 'hex' }
});

const emit = defineEmits(['update:value', 'change']);
const value = defineModel('value', String);

const [hexValue, setHexValue] = useState('');
const [rgbValue, setRgbValue] = useState({});
const [hsbValue, setHsbValue] = useState({});

onMounted(() => {
  formatValue(toValue(value), props.format);
});

watch(
  () => [value, props.format],
  ([color, format]) => {
    formatValue(toValue(color), format);
  },
  { deep: true }
);

/**
 * 格式化颜色
 *
 * @param val 颜色
 * @param format 格式
 * @returns {string} 格式化颜色
 */
const formatValue = (val, format) => {
  const color = formatColor(val, format);

  if (format === 'hex') {
    setHexValue(color.replace('#', ''));
  } else if (format === 'rgb') {
    const [r, g, b] = color.replace(/[^0-9,]/g, '').split(',');
    setRgbValue({ r, g, b });
  } else if (format === 'hsb') {
    const [h, s, b] = color.replace(/[^0-9,]/g, '').split(',');
    setHsbValue({ h, s, b });
  }
};

const onHexChange = (e) => {
  const color = e.target.value;
  const isHex = /^[0-9a-fA-F]{6}$/.test(color);
  if (isHex) {
    updateValue(`#${color}`);
  }
};

const onRgbChange = () => {
  const rgb = toValue(rgbValue);
  const color = `rgb(${rgb.r}, ${rgb.g}, ${rgb.b})`;
  updateValue(color);
};

const onHsbChange = () => {
  const hsb = toValue(hsbValue);
  const color = `hsb(${hsb.h}, ${hsb.s}%, ${hsb.b}%)`;
  updateValue(color);
};

const updateValue = (color) => {
  if (toValue(value) !== color) {
    emit('change', color);
    emit('update:value', color);
  }
};
</script>

<style lang="scss" scoped></style>
